home *** CD-ROM | disk | FTP | other *** search
/ Precision Software Appli…tions Silver Collection 1 / Precision Software Applications Silver Collection Volume One (PSM) (1993).iso / windows / games / wincapt.arj / DIBUTIL.C < prev    next >
Text File  |  1992-07-14  |  39KB  |  1,289 lines

  1. //**********************************************************************
  2. //
  3. //  dibutil.c
  4. //
  5. //  Source file for Device-Independent Bitmap (DIB) API.  Provides
  6. //  the following functions:
  7. //
  8. //  CreateDIB()         - Creates new DIB
  9. //  FindDIBBits()       - Sets pointer to the DIB bits
  10. //  DIBWidth()          - Gets the width of the DIB
  11. //  DIBHeight()         - Gets the height of the DIB
  12. //  PaletteSize()       - Calculates the buffer size required by a palette
  13. //  DIBNumColors()      - Calculates number of colors in the DIB's color table
  14. //  CreateDIBPalette()  - Creates a palette from a DIB
  15. //  DIBToBitmap()       - Creates a bitmap from a DIB
  16. //  BitmapToDIB()       - Creates a DIB from a bitmap
  17. //  PalEntriesOnDevice()- Gets the number of palette entries of a device
  18. //  GetSystemPalette()  - Returns a handle to the current system palette
  19. //  AllocRoomForDIB()   - Allocates memory for a DIB
  20. //  ChangeDIBFormat()   - Changes a DIB's BPP and/or compression format
  21. //  ChangeBitmapFormat()- Changes a bitmap to a DIB with specified BPP and
  22. //                        compression format
  23. //
  24. // Development Team: Mark Bader
  25. //                   Patrick Schreiber
  26. //                   Garrett McAuliffe
  27. //                   Eric Flo
  28. //                   Tony Claflin
  29. //
  30. // Written by Microsoft Product Support Services, Developer Support.
  31. // Copyright (c) 1991 Microsoft Corporation. All rights reserved.
  32. //**********************************************************************
  33.  
  34. /* header files */
  35. #include <windows.h>
  36. #include <assert.h>
  37. #include "dibapi.h"
  38. #include "dibutil.h"
  39. #include <stdio.h>
  40.  
  41.  
  42. /*************************************************************************
  43.  *
  44.  * CreateDIB()
  45.  *
  46.  * Parameters:
  47.  *
  48.  * DWORD dwWidth    - Width for new bitmap, in pixels
  49.  * DWORD dwHeight   - Height for new bitmap 
  50.  * WORD  wBitCount  - Bit Count for new DIB (1, 4, 8, or 24)
  51.  *
  52.  * Return Value:
  53.  *
  54.  * HDIB             - Handle to new DIB
  55.  *
  56.  * Description:
  57.  *
  58.  * This function allocates memory for and initializes a new DIB by
  59.  * filling in the BITMAPINFOHEADER, allocating memory for the color
  60.  * table, and allocating memory for the bitmap bits.  As with all
  61.  * HDIBs, the header, colortable and bits are all in one contiguous
  62.  * memory block.  This function is similar to the CreateBitmap() 
  63.  * Windows API.
  64.  *
  65.  * The colortable and bitmap bits are left uninitialized (zeroed) in the
  66.  * returned HDIB.
  67.  *
  68.  *
  69.  * History:   Date      Author              Reason
  70.  *            3/20/92   Mark Bader          Created
  71.  *
  72.  ************************************************************************/
  73.  
  74. HDIB FAR CreateDIB(DWORD dwWidth, DWORD dwHeight, WORD wBitCount)
  75. {
  76.    BITMAPINFOHEADER bi;         // bitmap header
  77.    LPBITMAPINFOHEADER lpbi;     // pointer to BITMAPINFOHEADER
  78.    DWORD dwLen;                 // size of memory block
  79.    HDIB hDIB;
  80.    DWORD dwBytesPerLine;        // Number of bytes per scanline
  81.  
  82.  
  83.    // Make sure bits per pixel is valid
  84.    if (wBitCount <= 1)
  85.       wBitCount = 1;
  86.    else if (wBitCount <= 4)
  87.       wBitCount = 4;
  88.    else if (wBitCount <= 8)
  89.       wBitCount = 8;
  90.    else if (wBitCount <= 24)
  91.       wBitCount = 24;
  92.    else
  93.       wBitCount = 4;  // set default value to 4 if parameter is bogus
  94.  
  95.    // initialize BITMAPINFOHEADER
  96.    bi.biSize = sizeof(BITMAPINFOHEADER);
  97.    bi.biWidth = dwWidth;         // fill in width from parameter
  98.    bi.biHeight = dwHeight;       // fill in height from parameter
  99.    bi.biPlanes = 1;              // must be 1
  100.    bi.biBitCount = wBitCount;    // from parameter
  101.    bi.biCompression = BI_RGB;    
  102.    bi.biSizeImage = 0;           // 0's here mean "default"
  103.    bi.biXPelsPerMeter = 0;
  104.    bi.biYPelsPerMeter = 0;
  105.    bi.biClrUsed = 0;
  106.    bi.biClrImportant = 0;
  107.  
  108.    // calculate size of memory block required to store the DIB.  This
  109.    // block should be big enough to hold the BITMAPINFOHEADER, the color
  110.    // table, and the bits
  111.  
  112.    dwBytesPerLine = WIDTHBYTES(wBitCount * dwWidth);
  113.    dwLen = bi.biSize + PaletteSize((LPSTR)&bi) + (dwBytesPerLine * dwHeight);
  114.  
  115.    // alloc memory block to store our bitmap
  116.    hDIB = GlobalAlloc(GHND, dwLen);
  117.  
  118.    // major bummer if we couldn't get memory block
  119.    if (!hDIB)
  120.    {
  121.       return NULL;
  122.    }
  123.  
  124.    // lock memory and get pointer to it
  125.    lpbi = (VOID FAR *)GlobalLock(hDIB);
  126.  
  127.    // use our bitmap info structure to fill in first part of
  128.    // our DIB with the BITMAPINFOHEADER
  129.    *lpbi = bi;
  130.  
  131.    // Since we don't know what the colortable and bits should contain,
  132.    // just leave these blank.  Unlock the DIB and return the HDIB.
  133.  
  134.    GlobalUnlock(hDIB);
  135.  
  136.    /* return handle to the DIB */
  137.    return hDIB;
  138. }
  139.  
  140.  
  141.  
  142. /*************************************************************************
  143.  *
  144.  * FindDIBBits()
  145.  *
  146.  * Parameter:
  147.  *
  148.  * LPSTR lpDIB      - pointer to packed-DIB memory block
  149.  *
  150.  * Return Value:
  151.  *
  152.  * LPSTR            - pointer to the DIB bits
  153.  *
  154.  * Description:
  155.  *
  156.  * This function calculates the address of the DIB's bits and returns a
  157.  * pointer to the DIB bits.
  158.  *
  159.  * History:   Date      Author              Reason
  160.  *            6/01/91   Garrett McAuliffe   Created
  161.  *            9/15/91   Patrick Schreiber   Added header and comments
  162.  *
  163.  ************************************************************************/
  164.  
  165.  
  166. LPSTR FAR FindDIBBits(LPSTR lpDIB)
  167. {
  168.    return (lpDIB + *(LPDWORD)lpDIB + PaletteSize(lpDIB));
  169. }
  170.  
  171.  
  172. /*************************************************************************
  173.  *
  174.  * DIBWidth()
  175.  *
  176.  * Parameter:
  177.  *
  178.  * LPSTR lpDIB      - pointer to packed-DIB memory block
  179.  *
  180.  * Return Value:
  181.  *
  182.  * DWORD            - width of the DIB
  183.  *
  184.  * Description:
  185.  *
  186.  * This function gets the width of the DIB from the BITMAPINFOHEADER
  187.  * width field if it is a Windows 3.0-style DIB or from the BITMAPCOREHEADER
  188.  * width field if it is an OS/2-style DIB.
  189.  *
  190.  * History:   Date      Author               Reason
  191.  *            6/01/91   Garrett McAuliffe    Created
  192.  *            9/15/91   Patrick Schreiber    Added header and comments
  193.  *
  194.  ************************************************************************/
  195.  
  196.  
  197. DWORD FAR DIBWidth(LPSTR lpDIB)
  198. {
  199.    LPBITMAPINFOHEADER lpbmi;  // pointer to a Win 3.0-style DIB
  200.    LPBITMAPCOREHEADER lpbmc;  // pointer to an OS/2-style DIB
  201.  
  202.    /* point to the header (whether Win 3.0 and OS/2) */
  203.  
  204.    lpbmi = (LPBITMAPINFOHEADER)lpDIB;
  205.    lpbmc = (LPBITMAPCOREHEADER)lpDIB;
  206.  
  207.    /* return the DIB width if it is a Win 3.0 DIB */
  208.    if (lpbmi->biSize == sizeof(BITMAPINFOHEADER))
  209.       return lpbmi->biWidth;
  210.    else  /* it is an OS/2 DIB, so return its width */
  211.       return (DWORD)lpbmc->bcWidth;
  212. }
  213.  
  214.  
  215. /*************************************************************************
  216.  *
  217.  * DIBHeight()
  218.  *
  219.  * Parameter:
  220.  *
  221.  * LPSTR lpDIB      - pointer to packed-DIB memory block
  222.  *
  223.  * Return Value:
  224.  *
  225.  * DWORD            - height of the DIB
  226.  *
  227.  * Description:
  228.  *
  229.  * This function gets the height of the DIB from the BITMAPINFOHEADER
  230.  * height field if it is a Windows 3.0-style DIB or from the BITMAPCOREHEADER
  231.  * height field if it is an OS/2-style DIB.
  232.  *
  233.  * History:   Date      Author               Reason
  234.  *            6/01/91   Garrett McAuliffe    Created
  235.  *            9/15/91   Patrick Schreiber    Added header and comments
  236.  *
  237.  ************************************************************************/
  238.  
  239.  
  240. DWORD FAR DIBHeight(LPSTR lpDIB)
  241. {
  242.    LPBITMAPINFOHEADER lpbmi;  // pointer to a Win 3.0-style DIB
  243.    LPBITMAPCOREHEADER lpbmc;  // pointer to an OS/2-style DIB
  244.  
  245.    /* point to the header (whether OS/2 or Win 3.0 */
  246.  
  247.    lpbmi = (LPBITMAPINFOHEADER)lpDIB;
  248.    lpbmc = (LPBITMAPCOREHEADER)lpDIB;
  249.  
  250.    /* return the DIB height if it is a Win 3.0 DIB */
  251.    if (lpbmi->biSize == sizeof(BITMAPINFOHEADER))
  252.       return lpbmi->biHeight;
  253.    else  /* it is an OS/2 DIB, so return its height */
  254.       return (DWORD)lpbmc->bcHeight;
  255. }
  256.  
  257.  
  258. /*************************************************************************
  259.  *
  260.  * PaletteSize()
  261.  *
  262.  * Parameter:
  263.  *
  264.  * LPSTR lpDIB      - pointer to packed-DIB memory block
  265.  *
  266.  * Return Value:
  267.  *
  268.  * WORD             - size of the color palette of the DIB
  269.  *
  270.  * Description:
  271.  *
  272.  * This function gets the size required to store the DIB's palette by
  273.  * multiplying the number of colors by the size of an RGBQUAD (for a
  274.  * Windows 3.0-style DIB) or by the size of an RGBTRIPLE (for an OS/2-
  275.  * style DIB).
  276.  *
  277.  * History:   Date      Author             Reason
  278.  *            6/01/91   Garrett McAuliffe  Created
  279.  *            9/15/91   Patrick Schreiber  Added header and comments
  280.  *
  281.  ************************************************************************/
  282.  
  283.  
  284. WORD FAR PaletteSize(LPSTR lpDIB)
  285. {
  286.    /* calculate the size required by the palette */
  287.    if (IS_WIN30_DIB (lpDIB))
  288.       return (DIBNumColors(lpDIB) * sizeof(RGBQUAD));
  289.    else
  290.       return (DIBNumColors(lpDIB) * sizeof(RGBTRIPLE));
  291. }
  292.  
  293.  
  294. /*************************************************************************
  295.  *
  296.  * DIBNumColors()
  297.  *
  298.  * Parameter:
  299.  *
  300.  * LPSTR lpDIB      - pointer to packed-DIB memory block
  301.  *
  302.  * Return Value:
  303.  *
  304.  * WORD             - number of colors in the color table
  305.  *
  306.  * Description:
  307.  *
  308.  * This function calculates the number of colors in the DIB's color table
  309.  * by finding the bits per pixel for the DIB (whether Win3.0 or OS/2-style
  310.  * DIB). If bits per pixel is 1: colors=2, if 4: colors=16, if 8: colors=256,
  311.  * if 24, no colors in color table.
  312.  *
  313.  * History:   Date      Author               Reason
  314.  *            6/01/91   Garrett McAuliffe    Created
  315.  *            9/15/91   Patrick Schreiber    Added header and comments
  316.  *
  317.  ************************************************************************/
  318.  
  319.  
  320. WORD FAR DIBNumColors(LPSTR lpDIB)
  321. {
  322.    WORD wBitCount;  // DIB bit count
  323.  
  324.    /*  If this is a Windows-style DIB, the number of colors in the
  325.     *  color table can be less than the number of bits per pixel
  326.     *  allows for (i.e. lpbi->biClrUsed can be set to some value).
  327.     *  If this is the case, return the appropriate value.
  328.     */
  329.  
  330.    if (IS_WIN30_DIB(lpDIB))
  331.    {
  332.       DWORD dwClrUsed;
  333.  
  334.       dwClrUsed = ((LPBITMAPINFOHEADER)lpDIB)->biClrUsed;
  335.       if (dwClrUsed)
  336.      return (WORD)dwClrUsed;
  337.    }
  338.  
  339.    /*  Calculate the number of colors in the color table based on
  340.     *  the number of bits per pixel for the DIB.
  341.     */
  342.    if (IS_WIN30_DIB(lpDIB))
  343.       wBitCount = ((LPBITMAPINFOHEADER)lpDIB)->biBitCount;
  344.    else
  345.       wBitCount = ((LPBITMAPCOREHEADER)lpDIB)->bcBitCount;
  346.  
  347.    /* return number of colors based on bits per pixel */
  348.    switch (wBitCount)
  349.       {
  350.    case 1:
  351.       return 2;
  352.  
  353.    case 4:
  354.       return 16;
  355.  
  356.    case 8:
  357.       return 256;
  358.  
  359.    default:
  360.       return 0;
  361.       }
  362. }
  363.  
  364.  
  365. /*************************************************************************
  366.  *
  367.  * CreateDIBPalette()
  368.  *
  369.  * Parameter:
  370.  *
  371.  * HDIB hDIB        - specifies the DIB
  372.  *
  373.  * Return Value:
  374.  *
  375.  * HPALETTE         - specifies the palette
  376.  *
  377.  * Description:
  378.  *
  379.  * This function creates a palette from a DIB by allocating memory for the
  380.  * logical palette, reading and storing the colors from the DIB's color table
  381.  * into the logical palette, creating a palette from this logical palette,
  382.  * and then returning the palette's handle. This allows the DIB to be
  383.  * displayed using the best possible colors (important for DIBs with 256 or
  384.  * more colors).
  385.  *
  386.  * History:   Date      Author               Reason
  387.  *            6/01/91   Garrett McAuliffe    Created
  388.  *            9/15/91   Patrick Schreiber    Added header and comments
  389.  *
  390.  ************************************************************************/
  391.  
  392.  
  393. HPALETTE FAR CreateDIBPalette(HDIB hDIB)
  394. {
  395.    LPLOGPALETTE lpPal;      // pointer to a logical palette
  396.    HANDLE hLogPal;          // handle to a logical palette
  397.    HPALETTE hPal = NULL;    // handle to a palette
  398.    int i, wNumColors;       // loop index, number of colors in color table
  399.    LPSTR lpbi;              // pointer to packed-DIB
  400.    LPBITMAPINFO lpbmi;      // pointer to BITMAPINFO structure (Win3.0)
  401.    LPBITMAPCOREINFO lpbmc;  // pointer to BITMAPCOREINFO structure (OS/2)
  402.    BOOL bWinStyleDIB;       // flag which signifies whether this is a Win3.0 DIB
  403.  
  404.    /* if handle to DIB is invalid, return NULL */
  405.  
  406.    if (!hDIB)
  407.       return NULL;
  408.  
  409.    /* lock DIB memory block and get a pointer to it */
  410.    lpbi = GlobalLock(hDIB);
  411.  
  412.    /* get pointer to BITMAPINFO (Win 3.0) */
  413.    lpbmi = (LPBITMAPINFO)lpbi;
  414.  
  415.    /* get pointer to BITMAPCOREINFO (OS/2 1.x) */
  416.    lpbmc = (LPBITMAPCOREINFO)lpbi;
  417.  
  418.    /* get the number of colors in the DIB */
  419.    wNumColors = DIBNumColors(lpbi);
  420.  
  421.    /* is this a Win 3.0 DIB? */
  422.    bWinStyleDIB = IS_WIN30_DIB(lpbi);
  423.    if (wNumColors)
  424.    {
  425.       /* allocate memory block for logical palette */
  426.       hLogPal = GlobalAlloc(GHND, sizeof(LOGPALETTE) + sizeof(PALETTEENTRY) *
  427.                 wNumColors);
  428.  
  429.       /* if not enough memory, clean up and return NULL */
  430.       if (!hLogPal)
  431.       {
  432.      GlobalUnlock(hDIB);
  433.      return NULL;
  434.       }
  435.  
  436.       /* lock memory block and get pointer to it */
  437.       lpPal = (LPLOGPALETTE)GlobalLock(hLogPal);
  438.  
  439.       /* set version and number of palette entries */
  440.       lpPal->palVersion = PALVERSION;
  441.       lpPal->palNumEntries = wNumColors;
  442.  
  443.       /*  store RGB triples (if Win 3.0 DIB) or RGB quads (if OS/2 DIB)
  444.        *  into palette
  445.        */
  446.       for (i = 0; i < wNumColors; i++)
  447.       {
  448.      if (bWinStyleDIB)
  449.      {
  450.         lpPal->palPalEntry[i].peRed = lpbmi->bmiColors[i].rgbRed;
  451.         lpPal->palPalEntry[i].peGreen = lpbmi->bmiColors[i].rgbGreen;
  452.         lpPal->palPalEntry[i].peBlue = lpbmi->bmiColors[i].rgbBlue;
  453.         lpPal->palPalEntry[i].peFlags = 0;
  454.      }
  455.      else
  456.      {
  457.         lpPal->palPalEntry[i].peRed = lpbmc->bmciColors[i].rgbtRed;
  458.         lpPal->palPalEntry[i].peGreen = lpbmc->bmciColors[i].rgbtGreen;
  459.         lpPal->palPalEntry[i].peBlue = lpbmc->bmciColors[i].rgbtBlue;
  460.         lpPal->palPalEntry[i].peFlags = 0;
  461.      }
  462.       }
  463.  
  464.       /* create the palette and get handle to it */
  465.       hPal = CreatePalette(lpPal);
  466.  
  467.       /* if error getting handle to palette, clean up and return NULL */
  468.       if (!hPal)
  469.       {
  470.      GlobalUnlock(hLogPal);
  471.      GlobalFree(hLogPal);
  472.      return NULL;
  473.       }
  474.    }
  475.  
  476.    /* clean up */
  477.    GlobalUnlock(hLogPal);
  478.    GlobalFree(hLogPal);
  479.    GlobalUnlock(hDIB);
  480.  
  481.    /* return handle to DIB's palette */
  482.    return hPal;
  483. }
  484.  
  485.  
  486. /*************************************************************************
  487.  *
  488.  * DIBToBitmap()
  489.  *
  490.  * Parameters:
  491.  *
  492.  * HDIB hDIB        - specifies the DIB to convert
  493.  *
  494.  * HPALETTE hPal    - specifies the palette to use with the bitmap
  495.  *
  496.  * Return Value:
  497.  *
  498.  * HBITMAP          - identifies the device-dependent bitmap
  499.  *
  500.  * Description:
  501.  *
  502.  * This function creates a bitmap from a DIB using the specified palette.
  503.  * If no palette is specified, default is used.
  504.  *
  505.  * NOTE:
  506.  *
  507.  * The bitmap returned from this funciton is always a bitmap compatible
  508.  * with the screen (e.g. same bits/pixel and color planes) rather than
  509.  * a bitmap with the same attributes as the DIB.  This behavior is by
  510.  * design, and occurs because this function calls CreateDIBitmap to
  511.  * do its work, and CreateDIBitmap always creates a bitmap compatible
  512.  * with the hDC parameter passed in (because it in turn calls
  513.  * CreateCompatibleBitmap).
  514.  *
  515.  * So for instance, if your DIB is a monochrome DIB and you call this
  516.  * function, you will not get back a monochrome HBITMAP -- you will
  517.  * get an HBITMAP compatible with the screen DC, but with only 2
  518.  * colors used in the bitmap.
  519.  *
  520.  * If your application requires a monochrome HBITMAP returned for a
  521.  * monochrome DIB, use the function SetDIBits().
  522.  *
  523.  * Also, the DIBpassed in to the function is not destroyed on exit. This
  524.  * must be done later, once it is no longer needed.
  525.  *
  526.  * History:   Date      Author               Reason
  527.  *            6/01/91   Garrett McAuliffe    Created
  528.  *            9/15/91   Patrick Schreiber    Added header and comments
  529.  *            3/27/92   Mark Bader           Added comments about resulting
  530.  *                                           bitmap format
  531.  *
  532.  ************************************************************************/
  533.  
  534.  
  535. HBITMAP FAR DIBToBitmap(HDIB hDIB, HPALETTE hPal)
  536. {
  537.    LPSTR lpDIBHdr, lpDIBBits;  // pointer to DIB header, pointer to DIB bits
  538.    HBITMAP hBitmap;            // handle to device-dependent bitmap
  539.    HDC hDC;                    // handle to DC
  540.    HPALETTE hOldPal = NULL;    // handle to a palette
  541.  
  542.    /* if invalid handle, return NULL */
  543.  
  544.    if (!hDIB)
  545.       return NULL;
  546.  
  547.    /* lock memory block and get a pointer to it */
  548.    lpDIBHdr = GlobalLock(hDIB);
  549.  
  550.    /* get a pointer to the DIB bits */
  551.    lpDIBBits = FindDIBBits(lpDIBHdr);
  552.  
  553.    /* get a DC */
  554.    hDC = GetDC(NULL);
  555.    if (!hDC)
  556.    {
  557.       /* clean up and return NULL */
  558.       GlobalUnlock(hDIB);
  559.       return NULL;
  560.    }
  561.  
  562.    /* select and realize palette */
  563.    if (hPal)
  564.       hOldPal = SelectPalette(hDC, hPal, FALSE);
  565.    RealizePalette(hDC);
  566.  
  567.    /* create bitmap from DIB info. and bits */
  568.    hBitmap = CreateDIBitmap(hDC, (LPBITMAPINFOHEADER)lpDIBHdr, CBM_INIT,
  569.                 lpDIBBits, (LPBITMAPINFO)lpDIBHdr, DIB_RGB_COLORS);
  570.  
  571.    /* restore previous palette */
  572.    if (hOldPal)
  573.       SelectPalette(hDC, hOldPal, FALSE);
  574.  
  575.    /* clean up */
  576.    ReleaseDC(NULL, hDC);
  577.    GlobalUnlock(hDIB);
  578.  
  579.    /* return handle to the bitmap */
  580.    return hBitmap;
  581. }
  582.  
  583.  
  584. /*************************************************************************
  585.  *
  586.  * BitmapToDIB()
  587.  *
  588.  * Parameters:
  589.  *
  590.  * HBITMAP hBitmap  - specifies the bitmap to convert
  591.  *
  592.  * HPALETTE hPal    - specifies the palette to use with the bitmap
  593.  *
  594.  * Return Value:
  595.  *
  596.  * HDIB             - identifies the device-dependent bitmap
  597.  *
  598.  * Description:
  599.  *
  600.  * This function creates a DIB from a bitmap using the specified palette.
  601.  *
  602.  * History:   Date      Author               Reason
  603.  *            6/01/91   Garrett McAuliffe    Created
  604.  *            9/15/91   Patrick Schreiber    Added header and comments
  605.  *            12/10/91  Patrick Schreiber    Added bits per pixel validation
  606.  *                                           and check GetObject return value
  607.  *
  608.  ************************************************************************/
  609.  
  610.  
  611. HDIB FAR BitmapToDIB(HBITMAP hBitmap, HPALETTE hPal)
  612. {
  613.    BITMAP bm;                   // bitmap structure
  614.    BITMAPINFOHEADER bi;         // bitmap header
  615.    BITMAPINFOHEADER FAR *lpbi;  // pointer to BITMAPINFOHEADER
  616.    DWORD dwLen;                 // size of memory block
  617.    HANDLE hDIB, h;              // handle to DIB, temp handle
  618.    HDC hDC;                     // handle to DC
  619.    WORD biBits;                 // bits per pixel
  620.  
  621.    /* check if bitmap handle is valid */
  622.  
  623.    if (!hBitmap)
  624.       return NULL;
  625.  
  626.    /* fill in BITMAP structure, return NULL if it didn't work */
  627.    if (!GetObject(hBitmap, sizeof(bm), (LPSTR)&bm))
  628.       return NULL;
  629.  
  630.    /* if no palette is specified, use default palette */
  631.    if (hPal == NULL)
  632.       hPal = GetStockObject(DEFAULT_PALETTE);
  633.  
  634.    /* calculate bits per pixel */
  635.    biBits = bm.bmPlanes * bm.bmBitsPixel;
  636.  
  637.    /* make sure bits per pixel is valid */
  638.    if (biBits <= 1)
  639.       biBits = 1;
  640.    else if (biBits <= 4)
  641.       biBits = 4;
  642.    else if (biBits <= 8)
  643.       biBits = 8;
  644.    else if (biBits <= 24)
  645.       biBits = 24;
  646.  
  647.    /* initialize BITMAPINFOHEADER */
  648.    bi.biSize = sizeof(BITMAPINFOHEADER);
  649.    bi.biWidth = bm.bmWidth;
  650.    bi.biHeight = bm.bmHeight;
  651.    bi.biPlanes = 1;
  652.    bi.biBitCount = biBits;
  653.    bi.biCompression = BI_RGB;
  654.    bi.biSizeImage = 0;
  655.    bi.biXPelsPerMeter = 0;
  656.    bi.biYPelsPerMeter = 0;
  657.    bi.biClrUsed = 0;
  658.    bi.biClrImportant = 0;
  659.  
  660.    /* calculate size of memory block required to store BITMAPINFO */
  661.    dwLen = bi.biSize + PaletteSize((LPSTR)&bi);
  662.  
  663.    /* get a DC */
  664.    hDC = GetDC(NULL);
  665.  
  666.    /* select and realize our palette */
  667.    hPal = SelectPalette(hDC, hPal, FALSE);
  668.    RealizePalette(hDC);
  669.  
  670.    /* alloc memory block to store our bitmap */
  671.    hDIB = GlobalAlloc(GHND, dwLen);
  672.  
  673.    /* if we couldn't get memory block */
  674.    if (!hDIB)
  675.    {
  676.       /* clean up and return NULL */
  677.       SelectPalette(hDC, hPal, TRUE);
  678.       RealizePalette(hDC);
  679.       ReleaseDC(NULL, hDC);
  680.       return NULL;
  681.    }
  682.  
  683.    /* lock memory and get pointer to it */
  684.    lpbi = (VOID FAR *)GlobalLock(hDIB);
  685.  
  686.    /* use our bitmap info. to fill BITMAPINFOHEADER */
  687.    *lpbi = bi;
  688.  
  689.    /*  call GetDIBits with a NULL lpBits param, so it will calculate the
  690.     *  biSizeImage field for us
  691.     */
  692.    GetDIBits(hDC, hBitmap, 0, (WORD)bi.biHeight, NULL, (LPBITMAPINFO)lpbi,
  693.          DIB_RGB_COLORS);
  694.  
  695.    /* get the info. returned by GetDIBits and unlock memory block */
  696.    bi = *lpbi;
  697.    GlobalUnlock(hDIB);
  698.  
  699.    /* if the driver did not fill in the biSizeImage field, make one up */
  700.    if (bi.biSizeImage == 0)
  701.       bi.biSizeImage = WIDTHBYTES((DWORD)bm.bmWidth * biBits) * bm.bmHeight;
  702.  
  703.    /* realloc the buffer big enough to hold all the bits */
  704.    dwLen = bi.biSize + PaletteSize((LPSTR)&bi) + bi.biSizeImage;
  705.    if (h = GlobalReAlloc(hDIB, dwLen, 0))
  706.       hDIB = h;
  707.    else
  708.    {
  709.       /* clean up and return NULL */
  710.       GlobalFree(hDIB);
  711.       hDIB = NULL;
  712.       SelectPalette(hDC, hPal, TRUE);
  713.       RealizePalette(hDC);
  714.       ReleaseDC(NULL, hDC);
  715.       return NULL;
  716.    }
  717.  
  718.    /* lock memory block and get pointer to it */
  719.    lpbi = (VOID FAR *)GlobalLock(hDIB);
  720.  
  721.    /*  call GetDIBits with a NON-NULL lpBits param, and actualy get the
  722.     *  bits this time
  723.     */
  724.    if (GetDIBits(hDC, hBitmap, 0, (WORD)bi.biHeight, (LPSTR)lpbi + (WORD)lpbi
  725.          ->biSize + PaletteSize((LPSTR)lpbi), (LPBITMAPINFO)lpbi,
  726.          DIB_RGB_COLORS) == 0)
  727.    {
  728.       /* clean up and return NULL */
  729.       GlobalUnlock(hDIB);
  730.       hDIB = NULL;
  731.       SelectPalette(hDC, hPal, TRUE);
  732.       RealizePalette(hDC);
  733.       ReleaseDC(NULL, hDC);
  734.       return NULL;
  735.    }
  736.    bi = *lpbi;
  737.  
  738.    /* clean up */
  739.    GlobalUnlock(hDIB);
  740.    SelectPalette(hDC, hPal, TRUE);
  741.    RealizePalette(hDC);
  742.    ReleaseDC(NULL, hDC);
  743.  
  744.    /* return handle to the DIB */
  745.    return hDIB;
  746. }
  747.  
  748.  
  749. /*************************************************************************
  750.  *
  751.  * PalEntriesOnDevice()
  752.  *
  753.  * Parameter:
  754.  *
  755.  * HDC hDC          - device context
  756.  *
  757.  * Return Value:
  758.  *
  759.  * int              - number of palette entries on device
  760.  *
  761.  * Description:
  762.  *
  763.  * This function gets the number of palette entries on the specified device
  764.  *
  765.  * History:   Date      Author               Reason
  766.  *            6/01/91   Garrett McAuliffe    Created
  767.  *            9/15/91   Patrick Schreiber    Added header and comments
  768.  *
  769.  ************************************************************************/
  770.  
  771.  
  772. int FAR PalEntriesOnDevice(HDC hDC)
  773. {
  774.    int nColors;  // number of colors
  775.  
  776.    /*  Find out the number of palette entries on this
  777.     *  device.
  778.     */
  779.  
  780.    nColors = GetDeviceCaps(hDC, SIZEPALETTE);
  781.  
  782.    /*  For non-palette devices, we'll use the # of system
  783.     *  colors for our palette size.
  784.     */
  785.    if (!nColors)
  786.       nColors = GetDeviceCaps(hDC, NUMCOLORS);
  787.    assert(nColors);
  788.    return nColors;
  789. }
  790.  
  791.  
  792. /*************************************************************************
  793.  *
  794.  * GetSystemPalette()
  795.  *
  796.  * Parameters:
  797.  *
  798.  * None
  799.  *
  800.  * Return Value:
  801.  *
  802.  * HPALETTE         - handle to a copy of the current system palette
  803.  *
  804.  * Description:
  805.  *
  806.  * This function returns a handle to a palette which represents the system
  807.  * palette.  The system RGB values are copied into our logical palette using
  808.  * the GetSystemPaletteEntries function.  
  809.  *
  810.  * History:   
  811.  *            
  812.  *    Date      Author               Reason        
  813.  *    6/01/91   Garrett McAuliffe    Created        
  814.  *    9/15/91   Patrick Schreiber    Added header and comments
  815.  *    12/20/91  Mark Bader           Added GetSystemPaletteEntries call
  816.  *
  817.  ************************************************************************/
  818.  
  819.  
  820. HPALETTE FAR GetSystemPalette(void)
  821. {
  822.    HDC hDC;                // handle to a DC
  823.    static HPALETTE hPal = NULL;   // handle to a palette
  824.    HANDLE hLogPal;         // handle to a logical palette
  825.    LPLOGPALETTE lpLogPal;  // pointer to a logical palette
  826.    int nColors;            // number of colors
  827.  
  828.    /* Find out how many palette entries we want. */
  829.  
  830.    hDC = GetDC(NULL);
  831.    if (!hDC)
  832.       return NULL;
  833.    nColors = PalEntriesOnDevice(hDC);   // Number of palette entries
  834.  
  835.    /* Allocate room for the palette and lock it. */
  836.    hLogPal = GlobalAlloc(GHND, sizeof(LOGPALETTE) + nColors * sizeof(
  837.              PALETTEENTRY));
  838.  
  839.    /* if we didn't get a logical palette, return NULL */
  840.    if (!hLogPal)
  841.       return NULL;
  842.  
  843.    /* get a pointer to the logical palette */
  844.    lpLogPal = (LPLOGPALETTE)GlobalLock(hLogPal);
  845.  
  846.    /* set some important fields */
  847.    lpLogPal->palVersion = PALVERSION;
  848.    lpLogPal->palNumEntries = nColors;
  849.  
  850.    /* Copy the current system palette into our logical palette */
  851.  
  852.    GetSystemPaletteEntries(hDC, 0, nColors, 
  853.                            (LPPALETTEENTRY)(lpLogPal->palPalEntry));
  854.  
  855.    /*  Go ahead and create the palette.  Once it's created,
  856.     *  we no longer need the LOGPALETTE, so free it.
  857.     */
  858.  
  859.    hPal = CreatePalette(lpLogPal);
  860.  
  861.    /* clean up */
  862.    GlobalUnlock(hLogPal);
  863.    GlobalFree(hLogPal);
  864.    ReleaseDC(NULL, hDC);
  865.  
  866.    return hPal;
  867. }
  868.  
  869.  
  870. /*************************************************************************
  871.  *
  872.  * AllocRoomForDIB()
  873.  *
  874.  * Parameters:
  875.  *
  876.  * BITMAPINFOHEADER - bitmap info header stucture
  877.  *
  878.  * HBITMAP          - handle to the bitmap
  879.  *
  880.  * Return Value:
  881.  *
  882.  * HDIB             - handle to memory block
  883.  *
  884.  * Description:
  885.  *
  886.  *  This routine takes a BITMAPINOHEADER, and returns a handle to global
  887.  *  memory which can contain a DIB with that header.  It also initializes
  888.  *  the header portion of the global memory.  GetDIBits() is used to determine
  889.  *  the amount of room for the DIB's bits.  The total amount of memory
  890.  *  needed = sizeof(BITMAPINFOHEADER) + size of color table + size of bits.
  891.  *
  892.  * History:   Date      Author               Reason
  893.  *            6/01/91   Garrett McAuliffe    Created
  894.  *            12/11/91  Patrick Schreiber    Added header and some comments
  895.  *
  896.  ************************************************************************/
  897.  
  898. HANDLE AllocRoomForDIB(BITMAPINFOHEADER bi, HBITMAP hBitmap)
  899. {
  900.    DWORD              dwLen;
  901.    HANDLE             hDIB;
  902.    HDC                hDC;
  903.    LPBITMAPINFOHEADER lpbi;
  904.    HANDLE             hTemp;
  905.  
  906.    /* Figure out the size needed to hold the BITMAPINFO structure
  907.     * (which includes the BITMAPINFOHEADER and the color table).
  908.     */
  909.  
  910.    dwLen = bi.biSize + PaletteSize((LPSTR) &bi);
  911.    hDIB  = GlobalAlloc(GHND,dwLen);
  912.  
  913.    /* Check that DIB handle is valid */
  914.    if (!hDIB)
  915.       return NULL;
  916.  
  917.    /* Set up the BITMAPINFOHEADER in the newly allocated global memory,
  918.     * then call GetDIBits() with lpBits = NULL to have it fill in the
  919.     * biSizeImage field for us.
  920.     */
  921.    lpbi  = (VOID FAR *)GlobalLock(hDIB);
  922.    *lpbi = bi;
  923.  
  924.    hDC   = GetDC(NULL);
  925.    GetDIBits(hDC, hBitmap, 0, (WORD) bi.biHeight,
  926.           NULL, (LPBITMAPINFO) lpbi, DIB_RGB_COLORS);
  927.    ReleaseDC(NULL, hDC);
  928.  
  929.    /* If the driver did not fill in the biSizeImage field,
  930.     * fill it in -- NOTE: this is a bug in the driver!
  931.     */
  932.    if (lpbi->biSizeImage == 0)
  933.       lpbi->biSizeImage = WIDTHBYTES((DWORD)lpbi->biWidth * lpbi->biBitCount) *
  934.               lpbi->biHeight;
  935.  
  936.    /* Get the size of the memory block we need */
  937.    dwLen = lpbi->biSize + PaletteSize((LPSTR) &bi) + lpbi->biSizeImage;
  938.  
  939.    /* Unlock the memory block */
  940.    GlobalUnlock(hDIB);
  941.  
  942.    /* ReAlloc the buffer big enough to hold all the bits */
  943.    if (hTemp = GlobalReAlloc(hDIB,dwLen,0))
  944.       return hTemp;
  945.    else
  946.       {
  947.       /* Else free memory block and return failure */
  948.       GlobalFree(hDIB);
  949.       return NULL;
  950.       }
  951. }
  952.  
  953.  
  954. /*************************************************************************
  955.  *
  956.  * ChangeDIBFormat()
  957.  *
  958.  * Parameter:
  959.  *
  960.  * HDIB             - handle to packed-DIB in memory
  961.  *
  962.  * WORD             - desired bits per pixel
  963.  *
  964.  * DWORD            - desired compression format
  965.  *
  966.  * Return Value:
  967.  *
  968.  * HDIB             - handle to the new DIB if successful, else NULL
  969.  *
  970.  * Description:
  971.  *
  972.  * This function will convert the bits per pixel and/or the compression
  973.  * format of the specified DIB. Note: If the conversion was unsuccessful,
  974.  * we return NULL. The original DIB is left alone. Don't use code like the
  975.  * following:
  976.  *
  977.  *    hMyDIB = ChangeDIBFormat(hMyDIB, 8, BI_RLE4);
  978.  *
  979.  * The conversion will fail, but hMyDIB will now be NULL and the original
  980.  * DIB will now hang around in memory. We could have returned the old
  981.  * DIB, but we wanted to allow the programmer to check whether this
  982.  * conversion succeeded or failed.
  983.  *
  984.  * History:   
  985.  *            
  986.  *   Date      Author             Reason         
  987.  *   6/01/91   Garrett McAuliffe  Created         
  988.  *   12/10/91  Patrick Schreiber  Modified from converting RGB to RLE8        
  989.  *                                  to converting RGB/RLE to RGB/RLE.         
  990.  *                                  Added wBitCount and dwCompression         
  991.  *                                  parameters. Also added header and         
  992.  *                                  comments.         
  993.  *
  994.  ************************************************************************/
  995.  
  996. HDIB FAR ChangeDIBFormat(HDIB hDIB, WORD wBitCount, DWORD dwCompression)
  997. {
  998.    HDC                hDC;             // Handle to DC
  999.    HBITMAP            hBitmap;         // Handle to bitmap
  1000.    BITMAP             Bitmap;          // BITMAP data structure
  1001.    BITMAPINFOHEADER   bi;              // Bitmap info header
  1002.    LPBITMAPINFOHEADER lpbi;            // Pointer to bitmap info
  1003.    HDIB               hNewDIB = NULL;  // Handle to new DIB
  1004.    HPALETTE           hPal, hOldPal;   // Handle to palette, prev pal
  1005.    WORD               DIBBPP, NewBPP;  // DIB bits per pixel, new bpp
  1006.    DWORD              DIBComp, NewComp;// DIB compression, new compression
  1007.  
  1008.    /* Check for a valid DIB handle */
  1009.    if (!hDIB)
  1010.       return NULL;
  1011.  
  1012.    /* Get the old DIB's bits per pixel and compression format */
  1013.    lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
  1014.    DIBBPP = ((LPBITMAPINFOHEADER)lpbi)->biBitCount;
  1015.    DIBComp = ((LPBITMAPINFOHEADER)lpbi)->biCompression;
  1016.    GlobalUnlock(hDIB);
  1017.  
  1018.    /* Validate wBitCount and dwCompression
  1019.     * They must match correctly (i.e., BI_RLE4 and 4 BPP or
  1020.     * BI_RLE8 and 8BPP, etc.) or we return failure */
  1021.    if (wBitCount == 0)
  1022.       {
  1023.       NewBPP = DIBBPP;
  1024.       if ((dwCompression == BI_RLE4 && NewBPP == 4) ||
  1025.       (dwCompression == BI_RLE8 && NewBPP == 8) ||
  1026.       (dwCompression == BI_RGB))
  1027.      NewComp = dwCompression;
  1028.       else
  1029.      return NULL;
  1030.       }
  1031.    else if (wBitCount == 1 && dwCompression == BI_RGB)
  1032.       {
  1033.       NewBPP = wBitCount;
  1034.       NewComp = BI_RGB;
  1035.       }
  1036.    else if (wBitCount == 4)
  1037.       {
  1038.       NewBPP = wBitCount;
  1039.       if (dwCompression == BI_RGB || dwCompression == BI_RLE4)
  1040.      NewComp = dwCompression;
  1041.       else
  1042.      return NULL;
  1043.       }
  1044.    else if (wBitCount == 8)
  1045.       {
  1046.       NewBPP = wBitCount;
  1047.       if (dwCompression == BI_RGB || dwCompression == BI_RLE8)
  1048.      NewComp = dwCompression;
  1049.       else
  1050.      return NULL;
  1051.       }
  1052.    else if (wBitCount == 24 && dwCompression == BI_RGB)
  1053.       {
  1054.       NewBPP = wBitCount;
  1055.       NewComp = BI_RGB;
  1056.       }
  1057.    else
  1058.       return NULL;
  1059.  
  1060.    /* Save the old DIB's palette */
  1061.    hPal = CreateDIBPalette(hDIB);
  1062.    if (!hPal)
  1063.       return NULL;
  1064.  
  1065.    /* Convert old DIB to a bitmap */
  1066.    hBitmap = DIBToBitmap(hDIB, hPal);
  1067.    if (!hBitmap)
  1068.       {
  1069.       DeleteObject(hPal);
  1070.       return NULL;
  1071.       }
  1072.  
  1073.    /* Get info about the bitmap */
  1074.    GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&Bitmap);
  1075.  
  1076.    /* Fill in the BITMAPINFOHEADER appropriately */
  1077.    bi.biSize               = sizeof(BITMAPINFOHEADER);
  1078.    bi.biWidth              = Bitmap.bmWidth;
  1079.    bi.biHeight             = Bitmap.bmHeight;
  1080.    bi.biPlanes             = 1;
  1081.    bi.biBitCount           = NewBPP;
  1082.    bi.biCompression        = NewComp;
  1083.    bi.biSizeImage          = 0;
  1084.    bi.biXPelsPerMeter      = 0;
  1085.    bi.biYPelsPerMeter      = 0;
  1086.    bi.biClrUsed            = 0;
  1087.    bi.biClrImportant       = 0;
  1088.  
  1089.    /* Go allocate room for the new DIB */
  1090.    hNewDIB = AllocRoomForDIB(bi, hBitmap);
  1091.    if (!hNewDIB)
  1092.       return NULL;
  1093.  
  1094.    /* Get a pointer to the new DIB */
  1095.    lpbi = (VOID FAR *)GlobalLock(hNewDIB);
  1096.  
  1097.    /* Get a DC and select/realize our palette in it */
  1098.    hDC  = GetDC(NULL);
  1099.    hOldPal = SelectPalette(hDC, hPal, FALSE);
  1100.    RealizePalette(hDC);
  1101.  
  1102.    /* Call GetDIBits and get the new DIB bits */
  1103.    if (!GetDIBits(hDC, hBitmap, 0, (WORD) lpbi->biHeight,
  1104.        (LPSTR)lpbi + (WORD)lpbi->biSize + PaletteSize((LPSTR)lpbi),
  1105.        (LPBITMAPINFO)lpbi, DIB_RGB_COLORS))
  1106.       {
  1107.       GlobalUnlock(hNewDIB);
  1108.       GlobalFree(hNewDIB);
  1109.       hNewDIB = NULL;
  1110.       }
  1111.  
  1112.    /* Clean up and return */
  1113.    SelectPalette(hDC, hOldPal, TRUE);
  1114.    RealizePalette(hDC);
  1115.    ReleaseDC(NULL, hDC);
  1116.  
  1117.    if (hNewDIB)
  1118.       /* Unlock the new DIB's memory block */
  1119.       GlobalUnlock(hNewDIB);
  1120.  
  1121.    DeleteObject(hBitmap);
  1122.    DeleteObject(hPal);
  1123.  
  1124.    return hNewDIB;
  1125. }
  1126.  
  1127.  
  1128. /*************************************************************************
  1129.  *
  1130.  * ChangeBitmapFormat()
  1131.  *
  1132.  * Parameter:
  1133.  *
  1134.  * HBITMAP          - handle to a bitmap
  1135.  *
  1136.  * WORD             - desired bits per pixel
  1137.  *
  1138.  * DWORD            - desired compression format
  1139.  *
  1140.  * HPALETTE         - handle to palette
  1141.  *
  1142.  * Return Value:
  1143.  *
  1144.  * HDIB             - handle to the new DIB if successful, else NULL
  1145.  *
  1146.  * Description:
  1147.  *
  1148.  * This function will convert a bitmap to the specified bits per pixel
  1149.  * and compression format. The bitmap and it's palette will remain
  1150.  * after calling this function.
  1151.  *
  1152.  * History:   
  1153.  *            
  1154.  *   Date      Author             Reason         
  1155.  *   6/01/91   Garrett McAuliffe  Created         
  1156.  *   12/10/91  Patrick Schreiber  Modified from converting RGB to RLE8         
  1157.  *                                 to converting RGB/RLE to RGB/RLE.         
  1158.  *                                 Added wBitCount and dwCompression         
  1159.  *                                 parameters. Also added header and         
  1160.  *                                 comments.         
  1161.  *   12/11/91  Patrick Schreiber  Destroy old DIB if conversion was         
  1162.  *                                 successful.         
  1163.  *   12/16/91  Patrick Schreiber  Modified from converting DIB to new         
  1164.  *                                 DIB to bitmap to new DIB. Added palette
  1165.  *                                 parameter.
  1166.  *
  1167.  ************************************************************************/
  1168.  
  1169. HDIB FAR ChangeBitmapFormat(HBITMAP  hBitmap,
  1170.             WORD     wBitCount,
  1171.             DWORD    dwCompression,
  1172.             HPALETTE hPal)
  1173. {
  1174.    HDC                hDC;          // Screen DC
  1175.    HDIB               hNewDIB=NULL; // Handle to new DIB
  1176.    BITMAP             Bitmap;       // BITMAP data structure
  1177.    BITMAPINFOHEADER   bi;           // Bitmap info. header
  1178.    LPBITMAPINFOHEADER lpbi;         // Pointer to bitmap header
  1179.    HPALETTE           hOldPal=NULL; // Handle to palette
  1180.    WORD               NewBPP;       // New bits per pixel
  1181.    DWORD              NewComp;      // New compression format
  1182.  
  1183.    /* Check for a valid bitmap handle */
  1184.    if (!hBitmap)
  1185.       return NULL;
  1186.  
  1187.    /* Validate wBitCount and dwCompression
  1188.     * They must match correctly (i.e., BI_RLE4 and 4 BPP or
  1189.     * BI_RLE8 and 8BPP, etc.) or we return failure
  1190.     */
  1191.    if (wBitCount == 0)
  1192.       {
  1193.       NewComp = dwCompression;
  1194.       if (NewComp == BI_RLE4)
  1195.      NewBPP = 4;
  1196.       else if (NewComp == BI_RLE8)
  1197.      NewBPP = 8;
  1198.       else /* Not enough info */
  1199.      return NULL;
  1200.       }
  1201.    else if (wBitCount == 1 && dwCompression == BI_RGB)
  1202.       {
  1203.       NewBPP = wBitCount;
  1204.       NewComp = BI_RGB;
  1205.       }
  1206.    else if (wBitCount == 4)
  1207.       {
  1208.       NewBPP = wBitCount;
  1209.       if (dwCompression == BI_RGB || dwCompression == BI_RLE4)
  1210.          NewComp = dwCompression;
  1211.       else
  1212.          return NULL;
  1213.       }
  1214.    else if (wBitCount == 8)
  1215.       {
  1216.       NewBPP = wBitCount;
  1217.       if (dwCompression == BI_RGB || dwCompression == BI_RLE8)
  1218.          NewComp = dwCompression;
  1219.       else
  1220.          return NULL;
  1221.       }
  1222.    else if (wBitCount == 24 && dwCompression == BI_RGB)
  1223.       {
  1224.       NewBPP = wBitCount;
  1225.       NewComp = BI_RGB;
  1226.       }
  1227.    else
  1228.       return NULL;
  1229.  
  1230.    /* Get info about the bitmap */
  1231.    GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&Bitmap);
  1232.  
  1233.    /* Fill in the BITMAPINFOHEADER appropriately */
  1234.    bi.biSize               = sizeof(BITMAPINFOHEADER);
  1235.    bi.biWidth              = Bitmap.bmWidth;
  1236.    bi.biHeight             = Bitmap.bmHeight;
  1237.    bi.biPlanes             = 1;
  1238.    bi.biBitCount           = NewBPP;
  1239.    bi.biCompression        = NewComp;
  1240.    bi.biSizeImage          = 0;
  1241.    bi.biXPelsPerMeter      = 0;
  1242.    bi.biYPelsPerMeter      = 0;
  1243.    bi.biClrUsed            = 0;
  1244.    bi.biClrImportant       = 0;
  1245.  
  1246.    /* Go allocate room for the new DIB */
  1247.    hNewDIB = AllocRoomForDIB(bi, hBitmap);
  1248.    if (!hNewDIB)
  1249.       return NULL;
  1250.  
  1251.    /* Get a pointer to the new DIB */
  1252.    lpbi = (VOID FAR *)GlobalLock(hNewDIB);
  1253.  
  1254.    /* If we have a palette, get a DC and select/realize it */
  1255.    if (hPal)
  1256.    {
  1257.       hDC  = GetDC(NULL);
  1258.       hOldPal = SelectPalette(hDC, hPal, FALSE);
  1259.       RealizePalette(hDC);
  1260.    }
  1261.  
  1262.    /* Call GetDIBits and get the new DIB bits */
  1263.    if (!GetDIBits(hDC, hBitmap, 0, (WORD) lpbi->biHeight,
  1264.        (LPSTR)lpbi + (WORD)lpbi->biSize + PaletteSize((LPSTR)lpbi),
  1265.        (LPBITMAPINFO)lpbi, DIB_RGB_COLORS))
  1266.       {
  1267.       GlobalUnlock(hNewDIB);
  1268.       GlobalFree(hNewDIB);
  1269.       hNewDIB = NULL;
  1270.       }
  1271.  
  1272.    /* Clean up and return */
  1273.    if (hOldPal)
  1274.    {
  1275.       SelectPalette(hDC, hOldPal, TRUE);
  1276.       RealizePalette(hDC);
  1277.       ReleaseDC(NULL, hDC);
  1278.    }
  1279.  
  1280.    if (hNewDIB)
  1281.       {
  1282.       /* Unlock the new DIB's memory block */
  1283.       GlobalUnlock(hNewDIB);
  1284.       }
  1285.  
  1286.    return hNewDIB;
  1287. }
  1288. 
  1289.